package cn.datawin.cmppserver.netway.handler;

import com.drondea.sms.channel.ChannelSession;
import com.drondea.sms.message.IMessage;
import com.drondea.sms.session.AbstractServerSession;
import com.drondea.sms.session.AbstractServerSessionManager;
import com.drondea.sms.type.DefaultEventGroupFactory;
import com.drondea.sms.type.ICustomHandler;
import com.drondea.sms.type.UserChannelConfig;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.Collectors;


/**
 * cmpp的定制处理器
 **/
@Slf4j
public class CmppServerCustomHandler extends ICustomHandler {

    public final static CmppServerBusinessHandler CMPP_SERVER_BUSINESS_HANDLER = new CmppServerBusinessHandler();

    /**
     * 用户登录校验方法
     * @param channel
     * @param channelSession
     */
    @Override
    public void fireUserLogin(Channel channel, ChannelSession channelSession) {

        AbstractServerSession serverSession = (AbstractServerSession) channelSession;
        UserChannelConfig userChannelConfig = serverSession.getUserChannelConfig();
        String account = userChannelConfig.getId();
        log.debug("用户{}登录了", account);
        String clientIp = ((InetSocketAddress) channel.remoteAddress()).getAddress().getHostAddress();
        int clientPort = ((InetSocketAddress) channel.remoteAddress()).getPort();
        log.debug("fireUserLogin account={} ip={} port={}", account, clientIp, clientPort);

        AbstractServerSessionManager sessionManager = (AbstractServerSessionManager) channelSession.getSessionManager();

        ScheduledExecutorService executor = DefaultEventGroupFactory.getInstance().getScheduleExecutor();
        executor.submit(() -> {
            //保存登录成功日志
            //SystemLogUtil.getInstance().saveLog(user, SessionStatus.LOGIN_SUCCESS, clientIp);
            countConnection(sessionManager, userChannelConfig.getUserName());
        });
    }

    /**
     * 统计连接数
     */
    private void countConnection(AbstractServerSessionManager abstractServerSessionManager, String tcpUserName) {
        if (abstractServerSessionManager == null) {
            return;
        }
        List<ChannelSession> userSessions = abstractServerSessionManager.getUserSessions(tcpUserName);
        if (userSessions == null) {
            return;
        }

        Map<String, Long> userIpCounting = userSessions.stream().collect(Collectors.groupingBy(userSession -> {
            Channel channel = userSession.getChannel();
            if (channel == null) {
                return "unknown";
            }
            return ((InetSocketAddress) channel.remoteAddress())
                .getAddress().getHostAddress();
        }, Collectors.counting()));

        log.debug("userIpCounting={}", userIpCounting);

    }

    @Override
    public void channelClosed(ChannelSession channelSession) {
        AbstractServerSession serverSession = (AbstractServerSession) channelSession;
        UserChannelConfig userChannelConfig = serverSession.getUserChannelConfig();
        String account = userChannelConfig.getId();

        AbstractServerSessionManager sessionManager = (AbstractServerSessionManager) channelSession.getSessionManager();

        String clientIp = ((InetSocketAddress) channelSession.getChannel().remoteAddress()).getAddress().getHostAddress();
        int clientPort = ((InetSocketAddress) channelSession.getChannel().remoteAddress()).getPort();
        log.debug("channelClosed account={} ip={} port={}", account, clientIp, clientPort);

        ScheduledExecutorService executor = DefaultEventGroupFactory.getInstance().getScheduleExecutor();
        executor.submit(() -> {
            //更新用户登录信息
            countConnection(sessionManager, userChannelConfig.getUserName());
            // TODO: 2022/11/30
        });
    }

    @Override
    public void responseMessageExpired(Integer sequenceId, IMessage request) {
        log.error("短信超时处理 {}", sequenceId);
    }

    @Override
    public void slidingWindowException(ChannelSession session, ChannelHandlerContext ctx, IMessage message, ChannelPromise promise, Exception exception) {
        log.error("slidingWindowException", exception);
    }

    @Override
    public boolean customLoginValidate(IMessage message, UserChannelConfig channelConfig, Channel channel) {
        return true;
    }

    @Override
    public void failedLogin(ChannelSession channelSession, IMessage iMessage, long status) {
        AbstractServerSession serverSession = (AbstractServerSession) channelSession;
        UserChannelConfig userChannelConfig = serverSession.getUserChannelConfig();
        String account = userChannelConfig.getId();

        String clientIp = ((InetSocketAddress) channelSession.getChannel().remoteAddress()).getAddress().getHostAddress();
        int clientPort = ((InetSocketAddress) channelSession.getChannel().remoteAddress()).getPort();
        log.error("failedLogin account={} ip={} port={} status={}", account, clientIp, clientPort, status);

        ScheduledExecutorService executor = DefaultEventGroupFactory.getInstance().getScheduleExecutor();
        executor.submit(() -> {
            //保存登录失败日志
            // TODO: 2022/11/30
            //SystemLogUtil.getInstance().saveLog(user, SessionStatus.valueOf((byte) status), clientIp);
        });
    }


    @Override
    public void configPipelineAfterLogin(ChannelPipeline pipeline) {
        pipeline.addLast("CmppServerBusinessHandler", CMPP_SERVER_BUSINESS_HANDLER);
    }

}
